/*
 * Copyright (C) 2015 Ingenic Electronics
 *
 * EDO 1.4 400*400 MIPI LCD Driver (driver's data part)
 *
 * Model : E1392AM1.A
 *
 * Author: MaoLei.Wang <maolei.wang@ingenic.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

//#define DEBUG
#include <config.h>
#include <serial.h>
#include <common.h>
#include <lcd.h>
#include <linux/list.h>
#include <linux/fb.h>
#include <asm/types.h>
#include <asm/arch/tcu.h>
#include <asm/arch/lcdc.h>
#include <asm/arch/gpio.h>
#include <regulator.h>

#include <jz_lcd/jz_dsim.h>
#include <jz_lcd/edo_e1392am1.h>

#include "../jz_mipi_dsi/jz_mipi_dsih_hal.h"

void panel_pin_init(void)
{
#ifdef DEBUG
	int ret= 0;

	ret = gpio_request(edo_e1392am1_pdata.gpio_rest, "lcd mipi panel rest");
	if (!ret) {
		debug("request edo_e1392am1 lcd mipi panel rest gpio failed\n");
		return;
	}

	ret = gpio_request(edo_e1392am1_pdata.gpio_lcd_bl,
			"lcd mipi brightness power eanble");
	if (!ret) {
		debug("request edo_e1392am1 lcd brightness power eanble gpio failed\n");
		return;
	}
#endif

	debug("edo_e1392am1 panel display pin init\n");

	return;
}

void panel_power_on(void)
{
	gpio_direction_output(edo_e1392am1_pdata.gpio_rest, 1);
	mdelay(50);
	gpio_direction_output(edo_e1392am1_pdata.gpio_rest, 0);  //reset active low
	mdelay(50);
	gpio_direction_output(edo_e1392am1_pdata.gpio_rest, 1);
	udelay(600);
	debug("edo_e1392am1 panel power on\n");

	return;
}

void edo_e1392am1_nop(struct dsi_device *dsi) /* nop */
{
	struct dsi_cmd_packet data_to_send = {0x15, 0x00, 0x00};

	write_command(dsi, data_to_send);
}

void edo_e1392am1_sleep_in(struct dsi_device *dsi) /* enter sleep */
{
	struct dsi_cmd_packet data_to_send = {0x15, 0x10, 0x00};

	write_command(dsi, data_to_send);
}

void edo_e1392am1_sleep_out(struct dsi_device *dsi) /* exit sleep */
{
	struct dsi_cmd_packet data_to_send = {0x15, 0x11, 0x00};

	write_command(dsi, data_to_send);
}

void edo_e1392am1_display_on(struct dsi_device *dsi) /* display on */
{
	struct dsi_cmd_packet data_to_send = {0x15, 0x29, 0x00};

	write_command(dsi, data_to_send);
}

void edo_e1392am1_display_off(struct dsi_device *dsi) /* display off */
{
	struct dsi_cmd_packet data_to_send = {0x15, 0x28, 0x00};

	write_command(dsi, data_to_send);
}

/*
 * display inversion on
 */
void edo_e1392am1_display_inversion_on(struct dsi_device *dsi)
{
	struct dsi_cmd_packet data_to_send = {0x15, 0x21, 0x00};

	write_command(dsi, data_to_send);
}

/*
 * display inversion off
 */
void edo_e1392am1_display_inversion_off(struct dsi_device *dsi)
{
	struct dsi_cmd_packet data_to_send = {0x15, 0x20, 0x00};

	write_command(dsi, data_to_send);
}

/*
 * display set pulse
 */
void edo_e1392am1_set_pulse(unsigned int level)
{
	unsigned long flags;
	unsigned int i;

	/* shut down it first */
	gpio_direction_output(edo_e1392am1_pdata.gpio_lcd_bl, 0);
	udelay(70);

	/* t_init and t_ss */
	gpio_direction_output(edo_e1392am1_pdata.gpio_lcd_bl, 1);
	udelay(350);
	udelay(1000);

	/* send the pulses */
	for (i = 0; i < level; ++i) {
		gpio_direction_output(edo_e1392am1_pdata.gpio_lcd_bl, 0);
		udelay(15);
		gpio_direction_output(edo_e1392am1_pdata.gpio_lcd_bl, 1);
		udelay(15);
	}

	/* store */
	udelay(55);

	/* wait it work */
	udelay(20000);

}

/**
 * lcd_open_backlight() - Overwrite the weak function defined at common/lcd.c
 */
void lcd_open_backlight(void)
{
	//gpio_direction_output(edo_e1392am1_pdata.gpio_lcd_bl, 1);
	edo_e1392am1_set_pulse(31);

	return;
}

/**
 * lcd_close_backlight() - Overwrite the weak function defined at common/lcd.c
 */
__weak void lcd_close_backlight(void)
{
	gpio_direction_output(edo_e1392am1_pdata.gpio_lcd_bl, 0);

	return;
}

void panel_display_on(struct dsi_device *dsi)
{
	return;
}

struct dsi_cmd_packet edo_e1392am1_cmd_list[] = {
		{0x15, 0xFE, 0x04},
		{0x15, 0x00, 0xdc},
		{0x15, 0x01, 0x00},
		{0x15, 0x02, 0x02},
		{0x15, 0x03, 0x00},
		{0x15, 0x04, 0x00},
		{0x15, 0x05, 0x03},
		{0x15, 0x06, 0x16},
		{0x15, 0x07, 0x13},
		{0x15, 0x08, 0x08},
		{0x15, 0x09, 0xdc},
		{0x15, 0x0a, 0x00},
		{0x15, 0x0b, 0x02},
		{0x15, 0x0c, 0x00},
		{0x15, 0x0d, 0x00},
		{0x15, 0x0e, 0x02},
		{0x15, 0x0f, 0x16},
		{0x15, 0x10, 0x18},
		{0x15, 0x11, 0x08},
		{0x15, 0x12, 0x92},
		{0x15, 0x13, 0x00},
		{0x15, 0x14, 0x02},
		{0x15, 0x15, 0x05},
		{0x15, 0x16, 0x40},
		{0x15, 0x17, 0x03},
		{0x15, 0x18, 0x16},
		{0x15, 0x19, 0xd7},
		{0x15, 0x1a, 0x01},
		{0x15, 0x1b, 0xdc},
		{0x15, 0x1c, 0x00},
		{0x15, 0x1d, 0x04},
		{0x15, 0x1e, 0x00},
		{0x15, 0x1f, 0x00},
		{0x15, 0x20, 0x03},
		{0x15, 0x21, 0x16},
		{0x15, 0x22, 0x18},
		{0x15, 0x23, 0x08},
		{0x15, 0x24, 0xdc},
		{0x15, 0x25, 0x00},
		{0x15, 0x26, 0x04},
		{0x15, 0x27, 0x00},
		{0x15, 0x28, 0x00},
		{0x15, 0x29, 0x01},
		{0x15, 0x2a, 0x16},
		{0x15, 0x2b, 0x18},
		{0x15, 0x2d, 0x08},
		{0x15, 0x4c, 0x99},
		{0x15, 0x4d, 0x00},
		{0x15, 0x4e, 0x00},
		{0x15, 0x4f, 0x00},
		{0x15, 0x50, 0x01},
		{0x15, 0x51, 0x0A},
		{0x15, 0x52, 0x00},
		{0x15, 0x5a, 0xe4},
		{0x15, 0x5e, 0x77},
		{0x15, 0x5f, 0x77},
		{0x15, 0x60, 0x34},
		{0x15, 0x61, 0x02},
		{0x15, 0x62, 0x81},
		{0x15, 0xFE, 0x07},
		{0x15, 0x07, 0x4F},
		{0x15, 0xFE, 0x01},
		{0x15, 0x05, 0x15},
		{0x15, 0x0E, 0x8B},
		{0x15, 0x0F, 0x8B},
		{0x15, 0x10, 0x11},
		{0x15, 0x11, 0xA2},
		{0x15, 0x12, 0x60},
		{0x15, 0x14, 0x01},
		{0x15, 0x15, 0x82},
		{0x15, 0x18, 0x47},
		{0x15, 0x19, 0x36},
		{0x15, 0x1A, 0x10},
		{0x15, 0x1C, 0x57},
		{0x15, 0x1D, 0x02},
		{0x15, 0x21, 0xF8},
		{0x15, 0x22, 0x90},
		{0x15, 0x23, 0x00},
		{0x15, 0x25, 0x03},
		{0x15, 0x26, 0x4a},
		{0x15, 0x2A, 0x47},
		{0x15, 0X2B, 0xFF},
		{0x15, 0x2D, 0XFF},
		{0x15, 0x2F, 0xAE},
		{0x15, 0x37, 0x0C},
		{0x15, 0x3a, 0x00},
		{0x15, 0x3b, 0x20},
		{0x15, 0x3d, 0x0B},
		{0x15, 0x3f, 0x38},
		{0x15, 0x40, 0x0B},
		{0x15, 0x41, 0x0B},
		{0x15, 0x42, 0x33},
		{0x15, 0x43, 0x66},
		{0x15, 0x44, 0x11},
		{0x15, 0x45, 0x44},
		{0x15, 0x46, 0x22},
		{0x15, 0x47, 0x55},
		{0x15, 0x4c, 0x33},
		{0x15, 0x4d, 0x66},
		{0x15, 0x4e, 0x11},
		{0x15, 0x4f, 0x44},
		{0x15, 0x50, 0x22},
		{0x15, 0x51, 0x55},
		{0x15, 0x56, 0x11},
		{0x15, 0x58, 0x44},
		{0x15, 0x59, 0x22},
		{0x15, 0x5a, 0x55},
		{0x15, 0x5b, 0x33},
		{0x15, 0x5c, 0x66},
		{0x15, 0x61, 0x11},
		{0x15, 0x62, 0x44},
		{0x15, 0x63, 0x22},
		{0x15, 0x64, 0x55},
		{0x15, 0x65, 0x33},
		{0x15, 0x66, 0x66},
		{0x15, 0x6d, 0x90},
		{0x15, 0x6E, 0x40},
		{0x15, 0x70, 0xA5},
		{0x15, 0x72, 0x04},
		{0x15, 0x73, 0x15},
		{0x15, 0xFE, 0x0A},
		{0x15, 0x29, 0x10},
		{0x15, 0xFE, 0x05},
		{0x15, 0x05, 0x1F},
		{0x15, 0xFE, 0x00},
		{0x15, 0x35, 0x00},
		{0x15, 0x11, 0x00},
};

void panel_init_set_sequence(struct dsi_device *dsi)
{
	int  i;

	edo_e1392am1_nop(dsi);
	mdelay(120);

	for(i = 0; i < ARRAY_SIZE(edo_e1392am1_cmd_list); i++) {
		write_command(dsi, edo_e1392am1_cmd_list[i]);
	}
	mdelay(120);

	edo_e1392am1_display_on(dsi);
	debug("init EDO 1.4 400*400 LCD...\n");

	return;
}

